package com.example.tangyee.activity;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.DatePickerDialog;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.widget.DatePicker;
import android.widget.TextView;

import com.example.tangyee.R;
import com.example.tangyee.bean.Exercise;
import com.example.tangyee.utils.ConstantsUtil;
import com.example.tangyee.utils.SessionidUtils;
import com.example.tangyee.view.MyCenterPopup;
import com.lxj.xpopup.XPopup;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 添加运动记录的Activity
 */
public class AddExerciseActivity extends AppCompatActivity implements DatePickerDialog.OnDateSetListener {

    private static final String TAG = "AddExerciseActivity";

    // 从intent中获取CircularReveal动画的起始点坐标的参数名
    public static final String EXTRA_CIRCULAR_REVEAL_X = "ecrX";
    public static final String EXTRA_CIRCULAR_REVEAL_Y = "ecrY";

    // 用于在界面销毁是解除ButterKnife的绑定
    private Unbinder mUnbinder;

    // CircularReveal动画开始的x,y坐标
    private int ecrX, ecrY;
    // CircularReveal动画的距离
    private float hypot;

    private View rootView;

    private SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日", Locale.CHINA);

    @BindView(R.id.time)
    TextView time; // 运动时长TextView
    @BindView(R.id.item)
    TextView item; // 运动项目TextView
    @BindView(R.id.date)
    TextView date; // 运动日期TextView
    @BindView(R.id.submit)
    TextView submit; // 提交按钮TextView

    // 运动时长，项目，项目代号，记录日期
    private String duration, sportItem, sportValue, recordDate;

    private GetExerciseItems mGetExerciseItems;
    private SetExerciseRecord mSetExerciseRecord;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_exercise);
        // rootView为当前界面最顶层的View
        rootView = findViewById(R.id.add_exercise_view);
        // 执行异步任务，展示CircularReveal动画
        rootView.post(() -> {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                ecrX = getIntent().getIntExtra(EXTRA_CIRCULAR_REVEAL_X,0);
                ecrY = getIntent().getIntExtra(EXTRA_CIRCULAR_REVEAL_Y,0);
                hypot = (float) Math.hypot(rootView.getWidth(), rootView.getHeight());
                Animator animator = ViewAnimationUtils.createCircularReveal(rootView, ecrX, ecrY, 0, hypot);
                animator.setDuration(800);
                animator.start();
            }
        });

        // 使用ButterKnife
        mUnbinder = ButterKnife.bind(this);
        // 初始化界面控件
        initViews();
    }

    /**
     * 初始化界面上的控件
     */
    private void initViews() {
        String[] items = new String[120];
        for (int i = 0; i < 120; i ++) {
            items[i] = (5 + i * 5) + "分钟";
        }
        time.setOnClickListener(v -> {
            XPopup.get(AddExerciseActivity.this).asCustom(new MyCenterPopup(AddExerciseActivity.this, items, new MyCenterPopup.PopupHelper(){
                @Override
                public String getTitle() {
                    return "运动时长";
                }

                @Override
                public void onSelect(View view, int position) {
                    duration = (5 + position * 5) + "";
                    time.setText(items[position]);
                    time.setTextColor(Color.BLACK);
                    submitState();
                }
            })).show();
        });
        // 为运动项TextView设置点击事件
        item.setOnClickListener(v -> {
            //显示加载弹窗
            XPopup.get(AddExerciseActivity.this).asLoading().show("loading");
            // 开启异步任务获取运动项
            mGetExerciseItems = new GetExerciseItems(ConstantsUtil.GET_EXERCISE_ITEMS);
            mGetExerciseItems.execute();
        });
        // 为选择日期的TextView设置显示日期弹窗的点击事件
        date.setOnClickListener(v -> {
            Calendar calendar = Calendar.getInstance();
            DatePickerDialog datePickerDialog = new DatePickerDialog(this, this, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
            datePickerDialog.getDatePicker().setMaxDate(new Date().getTime());
            datePickerDialog.show();
        });
        submit.setOnClickListener(v -> {
            switch (submitState()) {
                case 0:
                    XPopup.get(AddExerciseActivity.this).asLoading().show("loading");
                    mSetExerciseRecord = new SetExerciseRecord();
                    mSetExerciseRecord.execute();
                    break;
                case 1:
                    Snackbar.make(rootView, "请输入运动时长", Snackbar.LENGTH_SHORT).show();
                    break;
                case 2:
                    Snackbar.make(rootView, "请输入运动项目", Snackbar.LENGTH_SHORT).show();
                    break;
                case 3:
                    Snackbar.make(rootView, "请输入运动日期", Snackbar.LENGTH_SHORT).show();
                    break;
            }
        });
    }

    /**
     * 判断所有的应该输入的Item都已经输入了数据，否则将显示提示弹窗，不能进行提交操作
     *
     * @return 0表示可以提交 1表示运动时长未填写 2表示运动项目未填写 3表示记录日期没写
     */
    private int submitState() {
        if (duration == null) {
            return 1;
        } else if (sportValue == null) {
            return 2;
        } else if (recordDate == null) {
            return 3;
        }
        submit.setTextColor(Color.BLACK);
        return 0;
    }

    /**
     * 选择日期后将会回调此函数
     *
     * @param view 弹窗view
     * @param year 年份
     * @param month 月份-1
     * @param dayOfMonth 一月中的第几天
     */
    @Override
    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
        Date d = new GregorianCalendar(year, month, dayOfMonth, 0, 0, 0).getTime();
        if (new Date().getTime() >= d.getTime()) {
            date.setTextColor(Color.BLACK);
            date.setText(mSimpleDateFormat.format(d));
            recordDate = year + "/" + (month+1) + "/" + dayOfMonth;
            submitState();
        }
    }

    /**
     * 设置运动记录的异步任务
     */
    private class SetExerciseRecord extends AsyncTask<Void, Void, String>{

        /**
         * 在后台线程中发送post请求将数据保存到远程
         *
         * @param voids void
         * @return 保存失败时返回null
         */
        @Override
        protected String doInBackground(Void... voids) {
            if (isCancelled()) {
                return null;
            }
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .retryOnConnectionFailure(false)
                    .build();

            RequestBody body = new FormBody.Builder()
                    .add("recordDate",  recordDate)
                    .add("item", sportValue)
                    .add("duration", duration)
                    .build();
            Request request = new Request.Builder()
                    .url(ConstantsUtil.SET_EXERCISE_RECORD)
                    .addHeader("cookie", SessionidUtils.getCookie(AddExerciseActivity.this))
                    .post(body)
                    .build();

            try {
                Response response = okHttpClient.newCall(request).execute();
                if (response == null) { // TODO: 2019/3/16
                    return null;
                }
                return response.body().string();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String s) {
            if (s == null) {
                XPopup.get(AddExerciseActivity.this).dismiss("loading");
                Snackbar.make(rootView, "提交失败，服务器异常",Snackbar.LENGTH_SHORT).show();
                return;
            }
            if ("\"1\"".equals(s)) {
                Exercise exercise = new Exercise();
                exercise.setCalorie("");
                Intent intent = new Intent();
                intent.putExtra("result", exercise);
                AddExerciseActivity.this.setResult(1, intent);
                XPopup.get(AddExerciseActivity.this).dismiss("loading");
                onBackPressed();
                return;
            }
            if ("\"0\"".equals(s)) {
                XPopup.get(AddExerciseActivity.this).dismiss("loading");
                Snackbar.make(rootView, "提交失败，服务器异常",Snackbar.LENGTH_SHORT).show();
                return;
            }
            Log.d(TAG, "onPostExecute: " + s);
        }
    }

    private class GetExerciseItems extends AsyncTask<Void, Void, Map<String, Integer>> {

        private String url;

        GetExerciseItems(String url) {
            this.url = url;
        }

        @Override
        protected Map<String, Integer> doInBackground(Void... voids) {
            if (isCancelled()) {
                return null;
            }
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .retryOnConnectionFailure(false)
                    .build();

            RequestBody body = new FormBody.Builder()
                    .build();

            Request request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .build();

            String respStr = null;
            try {
                Response response = okHttpClient.newCall(request).execute();
                respStr = response.body().string();

                if (respStr == null) {
                    return null;
                }
            } catch (IOException e) {
                Log.e(TAG, "doInBackground: ", e);
            }
            Map<String, Integer> items = new LinkedHashMap<>();

            try {
                Log.i(TAG, "Received JSON: " + respStr);
                JSONArray jsonArray = new JSONArray(respStr);
                // 将json转成list
                parseItems(items, jsonArray);
            } catch (JSONException je) {
                Log.e(TAG, "Failed to parse JSON", je);
            }  catch (NullPointerException npe) {
                Log.e(TAG, "doInBackground: ", npe);
                return null;
            }

            return items;
        }

        @Override
        protected void onPostExecute(Map<String, Integer> integerStringMap) {
            XPopup.get(AddExerciseActivity.this).dismiss("loading");
            if (integerStringMap == null || integerStringMap.size() == 0) {
                // 请求未响应
                Snackbar.make(rootView, "请求超时", 300).show();
                return;
            }
            String[] items = new String[integerStringMap.size()];
            integerStringMap.keySet().toArray(items);
            XPopup.get(AddExerciseActivity.this).asCustom(new MyCenterPopup(AddExerciseActivity.this, items, new MyCenterPopup.PopupHelper(){
                @Override
                public String getTitle() {
                    return "运动时长";
                }

                @Override
                public void onSelect(View view, int position) {
                    sportItem = items[position];
                    item.setText(sportItem);
                    item.setTextColor(Color.BLACK);
                    sportValue = integerStringMap.get(sportItem).toString();
                    submitState();
                }
            })).show();
        }
    }

    private void parseItems(Map<String, Integer> items, JSONArray jsonArray) {
        for (int i = 0; i < jsonArray.length(); i ++) {
            try {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                int value = jsonObject.getInt("value");
                String text = jsonObject.getString("text");
                items.put(text, value);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onBackPressed() {
        Animator animator = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            animator = ViewAnimationUtils.createCircularReveal(rootView, ecrX, ecrY, hypot, 0);
            animator.setDuration(800);
            animator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    rootView.setVisibility(View.GONE);
                    finish();
                    // 很重要，不然会有activity退出的动画
                    overridePendingTransition(R.anim.no_anim,R.anim.no_anim);
                }
            });
            animator.start();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mSetExerciseRecord != null) {
            mSetExerciseRecord.cancel(true);
        }
        if (mGetExerciseItems != null) {
            mGetExerciseItems.cancel(true);
        }
        if (mUnbinder != null) {
            mUnbinder.unbind();
        }
    }
}
